home *** CD-ROM | disk | FTP | other *** search
/ Amiga Games: 500 MB Amiga Software / 500 MB Amiga Software - Euber 130 - Amiga Games Disc & Mag.iso / spiele / publicdomain / uchess / uchesssrc.lha / search.c < prev    next >
C/C++ Source or Header  |  1992-12-18  |  36KB  |  1,431 lines

  1. /*
  2.  * search.c - C source for GNU CHESS
  3.  *
  4.  * Copyright (c) 1988,1989,1990 John Stanback Copyright (c) 1992 Free Software
  5.  * Foundation
  6.  *
  7.  * This file is part of GNU CHESS.
  8.  *
  9.  * GNU Chess is free software; you can redistribute it and/or modify it under
  10.  * the terms of the GNU General Public License as published by the Free
  11.  * Software Foundation; either version 2, or (at your option) any later
  12.  * version.
  13.  *
  14.  * GNU Chess is distributed in the hope that it will be useful, but WITHOUT ANY
  15.  * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
  16.  * FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more
  17.  * details.
  18.  *
  19.  * You should have received a copy of the GNU General Public License along with
  20.  * GNU Chess; see the file COPYING.  If not, write to the Free Software
  21.  * Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
  22.  */
  23. #include "gnuchess.h"
  24. #ifdef QUIETBACKGROUND
  25. short background = 0;
  26.  
  27. #endif /* QUIETBACKGROUND */
  28. static short int DepthBeyond;
  29. unsigned short int PrVar[MAXDEPTH];
  30. extern char mvstr[4][6];
  31. extern short int recycle;
  32. #ifdef NULLMOVE
  33. short int null;         /* Null-move already made or not */
  34. short int PVari;        /* Is this the PV */
  35. #endif
  36. #ifdef DEBUG40
  37. extern int whichway;
  38. #endif
  39. #ifdef DEBUG
  40. unsigned short DBLINE[MAXDEPTH];
  41. struct leaf *dbptr;
  42.  
  43. #endif
  44. short int zwndw;
  45.  
  46. #include "ataks3.h"
  47.  
  48. #include <proto/exec.h>
  49.  
  50. int Sdepth2=0;
  51. extern int MoveNowOK;
  52. extern int procpri;
  53. extern struct Process *myproc;
  54.  
  55.  
  56. int Castled[2]={0,0};
  57. int myEnPassant[2]={0,0};
  58.  
  59.  
  60.  
  61. inline short int repetition (void);
  62.  
  63.  
  64. #include "debug41.h"
  65. /* ............    MOVE GENERATION & SEARCH ROUTINES    .............. */
  66.  
  67. inline
  68. short int
  69. repetition ()
  70.  
  71. /*  Check for draw by threefold repetition.  */
  72.  
  73. {
  74.   register short i, c,cnt;
  75.   register unsigned short m;
  76.   short b[64];
  77.  
  78.   cnt = c = 0;
  79.   /* try to avoid work */
  80.   if (GameCnt > Game50 + 2)
  81.     {
  82. #if defined(NOMEMSET) || defined(MSDOS)
  83.       for (i = 0; i < 64; b[i++] = 0);
  84. #else
  85.       memset ((char *) b, 0, (unsigned long)sizeof (b));
  86. #endif /* NOMEMSET */
  87.       for (i = GameCnt; i >= Game50; i--)
  88.     {
  89.       m = GameList[i].gmove;
  90.       /* does piece exist on diff board? */
  91.       if (b[m & 0xff])
  92.         {
  93.           /* does diffs cancel out, piece back? */
  94.           if ((b[m >> 8] += b[m & 0xff]) == 0)
  95.         --c;
  96.           b[m & 0xff] = 0;
  97.         }
  98.       else
  99.         {
  100.           /* create diff */
  101.           ++c;
  102.           /* does diff cancel out another diff? */
  103.           if (!(b[m >> 8] -= (b[m & 0xff] = board[m & 0xff] +
  104.                   (color[m & 0xff] << 8))))
  105.         --c;;
  106.         }
  107.       /* if diff count is 0 we have a repetition */
  108.       if (c == 0)
  109.         if ((i ^ GameCnt) & 1)
  110.           cnt++;
  111.     }
  112.     }
  113.     return cnt;
  114. }
  115.  
  116. int plyscore, globalscore;
  117. int
  118. pick (short int p1, short int p2)
  119.  
  120. /*
  121.  * Find the best move in the tree between indexes p1 and p2. Swap the best
  122.  * move into the p1 element.
  123.  *
  124.  */
  125. {
  126.   register struct leaf *p, *q, *r, *k;
  127.   register s0;
  128.   struct leaf temp;
  129.  
  130.   k = p = &Tree[p1];
  131.   q = &Tree[p2];
  132.   s0 = p->score;
  133.   for (r = p + 1; r <= q; r++)
  134.     if ((r->score) > s0)
  135.       {
  136.     s0 = (r->score);
  137.     p = r;
  138.       }
  139.   if (p != k)
  140.     {
  141.       temp = *p;
  142.       *p = *k;
  143.       *k = temp;
  144.       return true;
  145.     }
  146.   return false;
  147. }
  148.  
  149. #ifdef DEBUG
  150. unsigned short trace[MAXDEPTH];
  151. char traceline[256];
  152. unsigned short tracelog[MAXDEPTH];
  153. int tracen = 0;
  154. int traceflag = 0;
  155. int traceply = 0;
  156. #endif
  157. int bookflag = false;
  158.  
  159. static int TCcount, TCleft;
  160. void
  161. SelectMove (short int side, short int iop)
  162.  
  163.  
  164. /*
  165.  * Select a move by calling function search() at progressively deeper ply
  166.  * until time is up or a mate or draw is reached. An alpha-beta window of
  167.  * -Awindow to +Bwindow points is set around the score returned from the
  168.  * previous iteration. If Sdepth != 0 then the program has correctly
  169.  * predicted the opponents move and the search will start at a depth of
  170.  * Sdepth+1 rather than a depth of 1.
  171.  */
  172.  
  173. {
  174.   static short int i, tempb, tempc, tempsf, tempst, xside, rpt;
  175.   static short int alpha, beta, score;
  176.   static struct GameRec *g;
  177.   int Jscore = 0;
  178.   char mystr[16];
  179. #ifdef DEBUG
  180.  
  181. if(debuglevel & (512|1024)){
  182.     char b[32];
  183.     short c1,c2,r1,r2;
  184. tracen=0;
  185. traceflag = false;
  186. traceply = 0;
  187. tracelog[0]=0;
  188. while(true){
  189.     printf("debug?");
  190.     gets(b);
  191.     if(b[0] == 'p')traceply = atoi(&b[1]);
  192.     else
  193.     if(b[0] == '\0')break;
  194.     else{
  195.         c1 = b[0] - 'a';
  196.               r1 = b[1] - '1';
  197.               c2 = b[2] - 'a';
  198.               r2 = b[3] - '1';
  199.               trace[++tracen] = (locn (r1, c1) << 8) | locn (r2, c2);
  200.     }
  201.     if(tracen == 0 && traceply >0)traceflag = true;
  202.     }
  203.     
  204. }
  205. #endif
  206.  
  207.   flag.timeout = false;
  208.   flag.back = flag.musttimeout = false;
  209.   xside = side ^ 1;
  210.   recycle = (GameCnt % rehash) - rehash;
  211.   /* if background mode set to infinite */
  212.   if (iop == 2)
  213.     {
  214.       (void)SetTaskPri((struct Task *)myproc,0);
  215.       ResponseTime = 9999999;
  216. #ifdef QUIETBACKGROUND
  217.       background = true;
  218. #endif /* QUIETBACKGROUND */
  219.     }
  220.   else
  221.     {
  222.       player = side;
  223.       if (TCflag)
  224.     {
  225.       TCcount = 0;
  226. #ifdef QUIETBACKGROUND
  227.       background = false;
  228. #endif /* QUIETBACKGROUND */
  229.       if (TimeControl.moves[side] < 1)
  230.         TimeControl.moves[side] = 1;
  231.       /* special case time per move specified */
  232.       if (flag.onemove)
  233.         {
  234.           ResponseTime = TimeControl.clock[side] - 100;
  235.           TCleft = 0;
  236.         }
  237.       else
  238.         {
  239.           /* calculate avg time per move remaining */
  240.           TimeControl.clock[side] += TCadd;
  241.  
  242.           ResponseTime = (TimeControl.clock[side]) / (((TimeControl.moves[side]) * 2) + 1);
  243.           TCleft = (int)ResponseTime / 3;
  244.           ResponseTime += TCadd/2;
  245.           if (TimeControl.moves[side] < 5)
  246.         TCcount = MAXTCCOUNTX - 1;
  247.         }
  248.       if (ResponseTime < 100)
  249.         {
  250.           ResponseTime = 100;
  251.           TCcount = MAXTCCOUNTX;
  252.         }
  253.       else if (ResponseTime < 200)
  254.         {
  255.           TCcount = MAXTCCOUNTX - 1;
  256.         }
  257.     }
  258.       else
  259.     ResponseTime = MaxResponseTime;
  260.       if (TCleft)
  261.     {
  262.       TCcount = ((int)((TimeControl.clock[side] - ResponseTime)) / 2) / TCleft;
  263.       if (TCcount > MAXTCCOUNTX)
  264.         TCcount = 0;
  265.       else
  266.         TCcount = MAXTCCOUNTX - TCcount;
  267.     }
  268.       else
  269.     TCcount = MAXTCCOUNTX;
  270.     }
  271.  
  272.   if (MoveNowOK)
  273.    {
  274.     thinking2 = 1; /* allow move now menu item to work */
  275.    }
  276.   else
  277.    {
  278.     thinking2 = 0; /* do not allow move now menu item to work */
  279.    }
  280.   ExtraTime = 0;
  281.   ExaminePosition ();
  282.   score = ScorePosition (side);
  283. #ifdef QUIETBACKGROUND
  284.   if (!background)
  285. #endif /* QUIETBACKGROUND */
  286.     ShowSidetoMove ();
  287. #ifdef notdef
  288.   if (TCflag && TCcount < MAXTCCOUNT)
  289.     if (score < SCORETIME)
  290.       {
  291.     ExtraTime += TCleft;
  292.     TCcount++;
  293.       }
  294. #endif
  295.  
  296. #ifdef QUIETBACKGROUND
  297.   if (!background)
  298. #endif /* QUIETBACKGROUND */
  299.     SearchStartStuff (side);
  300. #ifdef HISTORY
  301. #if defined(NOMEMSET) || defined(MSDOS)
  302.   for (i = 0; i < 32768; i++)
  303.     history[i] = 0;
  304. #else
  305.   memset ((unsigned char *) history, 0, (unsigned long)sizeof (history));
  306. #endif /* NOMEMSET */
  307. #endif
  308.   FROMsquare = TOsquare = -1;
  309.   PV = 0;
  310.   if (iop == 1)
  311.     hint = 0;
  312.   for (i = 0; i < MAXDEPTH; i++)
  313.     PrVar[i] = killr0[i] = killr1[i] = killr2[i] = killr3[i] = 0;
  314.   /* set initial window for search */
  315.   alpha = score - ((computer == black) ? BAwindow : WAwindow);
  316.   beta = score + ((computer == black) ? BBwindow : WBwindow);
  317.   rpt = 0;
  318.   TrPnt[1] = 0;
  319.   root = &Tree[0];
  320.   MoveList (side, 1);
  321.   for (i = TrPnt[1]; i < TrPnt[2]; i++)
  322.     if (!pick (i, TrPnt[2] - 1))
  323.       break;
  324.   /* can I get a book move? */
  325.   if (flag.regularstart && Book)
  326.     {
  327.       flag.timeout = bookflag = OpeningBook (&hint, side);
  328.       if (TCflag)
  329.     ResponseTime += ResponseTime;
  330.     }
  331.   /* zero stats for hash table */
  332.   reminus = replus = 0;
  333.   GenCnt = NodeCnt = ETnodes = EvalNodes = HashCnt = FHashAdd = HashAdd = FHashCnt = THashCol = HashCol = 0;
  334.   globalscore = plyscore = score;
  335.   zwndw = 20;
  336. #include "debug4.h"
  337.   /********************* main loop ********************************/
  338.     Sdepth = (MaxSearchDepth<(MINDEPTH-1))?MaxSearchDepth:(MINDEPTH-1);
  339. /*printf("\n\n");*/
  340.   while (!flag.timeout)
  341.     {
  342. /*printf("time0 = %d et = %d SDepth = %d GameCnt = %d\n",time0, et,Sdepth,GameCnt);*/
  343. /*printf("ThinkAheadWorked = %d  ThinkAheadDepth = %d\n",ThinkAheadWorked,ThinkAheadDepth);*/
  344.       /* go down a level at a time */
  345.       Sdepth++;
  346. #ifdef NULLMOVE
  347.       null = 0;
  348.       PVari = 1;
  349. #endif
  350.       DepthBeyond = Sdepth + ((Sdepth == 1) ? 7 : 11);
  351.  
  352. #if !defined CHESSTOOL && !defined XBOARD
  353. #ifdef QUIETBACKGROUND
  354.       if (!background)
  355. #endif /* QUIETBACKGROUND */
  356.     ShowDepth (' ');
  357. #endif
  358.       /* search at this level returns score of PV */
  359.       score = search (side, 1, Sdepth, alpha, beta, PrVar, &rpt);
  360.       /* save PV as killer */
  361.       for (i = 1; i <= Sdepth; i++)
  362.     killr0[i] = PrVar[i];
  363.  
  364.       /* low search failure re-search with (-inf,score) limits  */
  365.       if (score < alpha)
  366.     {
  367. #if !defined CHESSTOOL && !defined XBOARD
  368.       reminus++;
  369. #ifdef QUIETBACKGROUND
  370.       if (!background)
  371. #endif /* QUIETBACKGROUND */
  372.         ShowDepth ('-');
  373. #endif
  374.       if (TCflag && TCcount < MAXTCCOUNTR)
  375.         {
  376.           TCcount = MAXTCCOUNTR - 1;
  377.           ExtraTime += (8 * TCleft);
  378.         }
  379.       score = search (side, 1, Sdepth, -9999, score, PrVar, &rpt);
  380.     }
  381.       /* high search failure re-search with (score, +inf) limits */
  382.       if (score > beta && !(root->flags & exact))
  383.     {
  384. #if !defined CHESSTOOL && !defined XBOARD
  385.       replus++;
  386. #ifdef QUIETBACKGROUND
  387.       if (!background)
  388. #endif /* QUIETBACKGROUND */
  389.         ShowDepth ('+');
  390. #endif
  391.       score = search (side, 1, Sdepth, score, 9999, PrVar, &rpt);
  392.     }
  393.       /**************** out of search ********************************************/
  394.       if (flag.musttimeout || Sdepth >= MaxSearchDepth)
  395.     flag.timeout = true;
  396.  
  397.       else if (TCflag && (Sdepth > (MINDEPTH - 1)) && (TCcount < MAXTCCOUNTR))
  398.     {
  399.       if (killr0[1] != PrVar[1] /* || Killr0[2] != PrVar[2] */ )
  400.         {
  401.           TCcount++;
  402.           ExtraTime += TCleft;
  403.         }
  404.       if ((abs (score - globalscore) / Sdepth) > ZDELTA)
  405.         {
  406.           TCcount++;
  407.           ExtraTime += TCleft;
  408.         }
  409.     }
  410.       if (score > (Jscore - zwndw) && score > (Tree[1].score + 250)) ExtraTime = 0;
  411. /*printf("sdepth = %d mindepth = %d TCflag = %d \n4*et = %d respt = %d extra = %d\n",Sdepth,MINDEPTH,TCflag,4*et,ResponseTime,ExtraTime);*/
  412.       if (root->flags & exact) flag.timeout = true;
  413.       /*else if (Tree[1].score < -9000) flag.timeout = true;*/
  414.       else if (!(Sdepth < MINDEPTH) && TCflag && ((4 * et) > (2*ResponseTime + ExtraTime))) flag.timeout = true;
  415.       /************************ time control ***********************************/
  416.  
  417.       /* save PV as killer */
  418.       for (i = 1; i <= Sdepth + 1; i++) killr0[i] = PrVar[i];
  419.       if (!flag.timeout) Tscore[0] = score;
  420.       /* if (!flag.timeout) */
  421.       for (i = TrPnt[1]+1; i < TrPnt[2]; i++) if (!pick (i, TrPnt[2] - 1)) break;
  422.       /* if done or nothing good to look at quit */
  423.       if ((root->flags & exact) || (score < -9000)) flag.timeout = true;
  424.       /* find the next best move put below root */
  425. #include "debug13.h"
  426.       if (!flag.timeout)
  427.     {
  428.       /* */
  429. #if !defined NODYNALPHA
  430.       Jscore = (plyscore + score) >> 1;
  431. #endif
  432.       zwndw = 20 + abs (Jscore / 12);
  433.       plyscore = score;
  434.       /* recompute search window */
  435.       beta = score + ((computer == black) ? BBwindow : WBwindow);
  436. #if !defined NODYNALPHA
  437.       alpha = ((Jscore < score) ? Jscore : score) - ((computer == black) ? BAwindow : WAwindow) - zwndw;
  438. #else
  439.       alpha = score - ((computer == black) ? BAwindow : WAwindow);
  440. #endif
  441.     }
  442. #if !defined CHESSTOOL && !defined XBOARD
  443. #ifdef QUIETBACKGROUND
  444.       if (!background)
  445. #endif /* QUIETBACKGROUND */
  446.     ShowResults (score, PrVar, '.');
  447. #ifdef DEBUG41
  448.       debug41 (score, PrVar, '.');
  449. #endif
  450. #endif
  451. #include "debug16.h"
  452.     }
  453.   /******************************* end of main loop ***********************************/
  454.   /* background mode */
  455.   if (iop == 2)
  456.     return;
  457. #include "debug4.h"
  458.   if (rpt >= 2)
  459.     {
  460.       root->flags |= draw;
  461.       DRAW = CP[101];        /* Repetition */
  462.     }
  463.   else
  464.     /* if no moves and not in check then draw */
  465.   if ((score == -9999) && !(SqAtakd3 (PieceList[side][0], xside)))
  466.     {
  467.       root->flags |= draw;
  468.       DRAW = CP[87];        /* No moves */
  469.     }
  470.   else if (GameCnt == MAXMOVES)
  471.     {
  472.       root->flags |= draw;
  473.       DRAW = CP[80];        /* Max Moves */
  474.     }
  475.   /* not in book so set hint to guessed move for other side */
  476.   if (!bookflag)
  477.     hint = ((PrVar[1]) ? PrVar[2] : 0);
  478.  
  479.   /* if not mate or draw make move and output it */
  480.   if (((score > -9999) && (rpt <= 2)) || (root->flags & draw))
  481.     {
  482.       MakeMove (side, &Tree[0], &tempb, &tempc, &tempsf, &tempst, &INCscore);
  483. #if !defined NOMATERIAL
  484.       if (flag.material && !pmtl[black] && !pmtl[white] && (mtl[white] < (valueR + valueK)) && (mtl[black] < (valueR + valueK)))
  485.     {
  486.       root->flags |= draw;
  487.       DRAW = CP[224];    /* No pieces */
  488.     }
  489.       else
  490. #endif
  491.       if (!PieceCnt[black] && !PieceCnt[white])
  492.     {
  493.       root->flags |= draw;
  494.       DRAW = CP[88];    /* No pieces */
  495.     }
  496.       algbr (root->f, root->t, (short) root->flags);
  497.     }
  498.   else
  499.     {
  500.       algbr (0, 0, 0);        /* Zero move string when mate. */
  501.       root->score = score;    /* When mate, ignore distinctions!
  502.                  * --SMC */
  503.     }
  504.   g = &GameList[GameCnt];
  505.   if (g->flags & capture && g->piece == king)
  506.     {
  507.       flag.mate = flag.illegal = true;
  508.     }
  509.   /* If Time Control get the elapsed time */
  510.   if (TCflag)
  511.     ElapsedTime (1);
  512.   OutputMove (mystr);
  513.   /* if mate set flag */
  514.   if ((score == -9999 || score == 9998))
  515.     flag.mate = true;
  516.   /* if mate clear hint */
  517.   if (flag.mate)
  518.     hint = 0;
  519.   /* if pawn move or capture or castle or promote zero repitition array */
  520.   if ((board[root->t] == pawn) || (root->flags & (capture | cstlmask | promote)))
  521.     {
  522.       Game50 = GameCnt;
  523.       ZeroRPT ();
  524.     }
  525.   /* add move to game list */
  526.   g->score = score;
  527.   g->nodes = NodeCnt;
  528.   g->time = (et +50)/100;
  529.   g->depth = Sdepth;
  530. #include "debug40.h"
  531.   /* update time comtrol info */
  532.   if (TCflag)
  533.     {
  534. #if defined CHESSTOOL || defined XBOARD
  535.       TimeControl.clock[side] -= (et + OperatorTime + 45);
  536.       timecomp[compptr] = (et + OperatorTime + 45);
  537. #else
  538.       TimeControl.clock[side] -= (et + OperatorTime);
  539.       timecomp[compptr] = (et + OperatorTime);
  540. #endif
  541.       /* finished our required moves - setup the next set */
  542.       --TimeControl.moves[side];
  543.     }
  544.   /* check for end conditions */
  545.   if ((root->flags & draw) /* && flag.bothsides */ )
  546. #if !defined CLIENT
  547.      flag.mate = true;
  548. #else 
  549.     ;
  550. #endif
  551.   else if (GameCnt == MAXMOVES)
  552.     {
  553.       flag.mate = true;
  554.     }
  555.   /* out of move store, you loose */
  556.   else
  557.     /* switch to other side */
  558.     player = xside;
  559.   if (!flag.easy)
  560.    {
  561.     Sdepth2 = Sdepth;
  562.    }
  563.   Sdepth = 0;
  564. }
  565.  
  566. int
  567. search (short int side,
  568.     register short int ply,
  569.     register short int depth,
  570.     short int alpha,
  571.     short int beta,
  572.     short unsigned int *bstline,
  573.     short int *rpt)
  574.  
  575. /*
  576.  * Perform an alpha-beta search to determine the score for the current board
  577.  * position. If depth <= 0 only capturing moves, pawn promotions and
  578.  * responses to check are generated and searched, otherwise all moves are
  579.  * processed. The search depth is modified for check evasions, certain
  580.  * re-captures and threats. Extensions may continue for up to 11 ply beyond
  581.  * the nominal search depth.
  582.  */
  583.  
  584.  
  585. {
  586.   register short j, pnt;
  587.   short tempb, tempc, tempsf, tempst;
  588.   short xside, pbst, score, rcnt, InChk;
  589.   unsigned short mv, nxtline[MAXDEPTH];
  590.   struct leaf *node, tmp;
  591.   short best = -12000;
  592.   short bestwidth = 0;
  593. #ifdef NULLMOVE
  594. #ifndef AMIGA
  595.   short int PVsave;
  596. #endif
  597.   short int PVarisave;
  598. #endif
  599. #ifdef DEBUG
  600.   int xxxtmp;
  601.   int tracetmp;
  602. #endif
  603.   NodeCnt++;
  604.   /* look every ZNODE nodes for a timeout */
  605.   if (!null && NodeCnt > ETnodes )
  606.     {
  607.       ElapsedTime (2);
  608.       if (flag.back)
  609.     {
  610.       flag.back = false;
  611.       flag.timeout = true;
  612.       flag.musttimeout = false;
  613.     }
  614.       else if (TCflag || MaxResponseTime)
  615.     {
  616.       if ((et >= (ResponseTime + ExtraTime)) && Sdepth > MINDEPTH && abs(best) < 10000)
  617.         {            /* try to extend to finish ply */
  618. #ifdef TRYEXTEND
  619.           if (TCflag && TCcount < MAXTCCOUNTX)
  620.         {
  621.           flag.musttimeout = true;
  622.           TCcount += 1;
  623.           ExtraTime += TCleft;
  624.         }
  625.           else
  626.         {
  627.           flag.timeout = true;
  628.           flag.musttimeout = false;
  629.         }
  630. #else
  631.           if ((TCflag && TCcount < MAXTCCOUNTX)&&(flag.easy))
  632.         {
  633.           flag.musttimeout = true;
  634.           TCcount += 1;
  635.           ExtraTime += TCleft;
  636.         }
  637.           else
  638.         {
  639.           flag.timeout = true;
  640.           flag.musttimeout = false;
  641.         }
  642. #endif
  643.         }
  644.     }
  645.     }
  646.   else if (!TCflag && flag.musttimeout && Sdepth > MINDEPTH)
  647.     {
  648.       flag.timeout = true;
  649.       flag.musttimeout = false;
  650.     }
  651.   xside = side ^ 1;
  652.   /* slk is lone king indicator for either side */
  653.   score = evaluate (side, ply, alpha, beta, INCscore, &InChk);
  654.  
  655.   /*
  656.    * check for possible repitition if so call repitition - rpt is
  657.    * repeat count
  658.    */
  659.   if ((ply <= Sdepth + 3) && rpthash[side][hashkey & 0xFF] > 0)
  660.     {
  661.       *rpt = repetition ();
  662.  
  663.       /*
  664.        * repeat position >2 don't need to return score it's taken
  665.        * care of above
  666.        */
  667.       if (*rpt == 1) score /= 2;
  668.     }
  669.   else
  670.     *rpt = 0;
  671.  
  672.   /* score > 9000 its a draw or mate */
  673.   if (score > 9000)
  674.     {
  675.       bstline[ply] = 0;
  676.       return (score);
  677.     }
  678.   /* Do we need to add depth because of special conditions */
  679.   /* if in check or pawn threat or in capture sequence search deeper */
  680.   /*************************************** depth extensions ***********************************/
  681.   if (depth > 0)
  682.     {
  683.       /* Allow opponent a chance to check again */
  684.       if (InChk)
  685.     depth = (depth < 2) ? 2 : depth;
  686.       else if (PawnThreat[ply - 1] ||
  687.            (flag.rcptr && (score > alpha) &&
  688.       (score < beta) && (ply > 2) && CptrFlag[ply - 1] && CptrFlag[ply - 2]))
  689.     ++depth;
  690.     }
  691.   else 
  692.     {
  693.       if (score >= alpha &&
  694.       (InChk || PawnThreat[ply - 1] || (hung[side] > 1 && ply == Sdepth + 1)))
  695.     depth = 1;
  696.       else if (score <= beta &&
  697.            ((ply < Sdepth + 4) && (ply > 4) &&
  698.         ChkFlag[ply - 2] && ChkFlag[ply - 4] &&
  699.         ChkFlag[ply - 2] != ChkFlag[ply - 4]))
  700.     depth = 1;
  701.     }
  702.   /*******************************************************************************************/
  703.   /* try the local transition table if it's there */
  704. #if ttblsz
  705.   if (/*depth > 0 &&*/ flag.hash && ply > 1)
  706.     {
  707.       if (ProbeTTable (side, depth, ply, &alpha, &beta, &score) == true)
  708.     {
  709.       bstline[ply] = PV;
  710.       bstline[ply + 1] = 0;
  711. #include "debug64.h"
  712.       if (beta == -20000)
  713.         return (score);
  714.       if (alpha > beta)
  715.         return (alpha);
  716.     }
  717. #ifdef HASHFILE
  718.       /* ok try the transition file if its there */
  719.       else if (hashfile && (depth > HashDepth) && (GameCnt < HashMoveLimit)
  720.      && (ProbeFTable (side, depth, ply, &alpha, &beta, &score) == true))
  721.     {
  722. #ifdef notdef
  723.       int hgood = false;
  724.       int f = PV >> 8;
  725.       int t = PV & 0x3f;
  726.       register int i;
  727.  
  728.       /*
  729.        * if you find something put it in the local table
  730.        * for future reference
  731.        */
  732.       hgood = false;
  733.       for (i = TrPnt[ply]; i < TrPnt[ply + 1]; i++)
  734.         {
  735.           if (Tree[i].f == f && Tree[i].t == t)
  736.         {
  737.           hgood = true;
  738.           break;
  739.         }
  740.         }
  741.       if (hgood)
  742.         {
  743. #endif
  744.           PutInTTable (side, score, depth, ply, alpha, beta, PV);
  745.           bstline[ply] = PV;
  746.           bstline[ply + 1] = 0;
  747.           if (beta == -20000)
  748.         return (score);
  749.           if (alpha > beta)
  750.         return (alpha);
  751. #ifdef notdef
  752.         }
  753. #endif
  754. #include "debug10.h"
  755.     }
  756. #endif /* HASHFILE */
  757.     }
  758. #endif /* ttblsz */
  759.  
  760.   /*
  761.    * if more then DepthBeyond ply past goal depth or at goal depth and
  762.    * score > beta quit - means we are out of the window
  763.    */
  764.   if (ply > DepthBeyond || (depth < 1 && score > beta))
  765.     {
  766.       return (score);
  767.     }
  768.  
  769.   /*
  770.    * if below first ply and not at goal depth generate all moves else
  771.    * only capture moves
  772.    */
  773.   if (ply > 1)
  774.     if (depth > 0  || ply<(Sdepth+2)|| (background && ply<Sdepth + 2))
  775.       {
  776.     MoveList (side, ply);
  777.       }
  778.     else{
  779.       CaptureList (side, ply);
  780.     }
  781.  
  782.   /* no moves return what we have */
  783.  
  784.   /*
  785.    * normally a search will continue til past goal and no more capture
  786.    * moves exist
  787.    */
  788.   /* unless it hits DepthBeyond */
  789.   if (TrPnt[ply] == TrPnt[ply + 1])
  790.     {
  791.       return (score);
  792.     }
  793.  
  794.  
  795.  
  796.   /* if not at goal set best = -inf else current score */
  797.      best = (depth >0)?-12000:score;
  798. #ifdef NULLMOVE
  799.  
  800.   PVarisave = PVari;
  801.   if (!null &&                         /* no previous null-move */
  802.       !PVari &&                        /* no null-move during the PV */
  803.       (ply > 1) &                       /* not at ply 1 */
  804.       (depth > 1) &&                   /* not during the quienscesearch */
  805.       !InChk &&                        /* no check */
  806.       ((mtl[side] + mtl[xside]) > 4000))
  807.     /* enough material such that zugzwang is unlike but who knows which value
  808.        is suitable? */
  809.     {
  810.       
  811.       /* ok, we make a null move, i.e.  this means we have nothing to do
  812.       but we have to keep the some arrays up to date otherwise gnuchess
  813.       gets confused.  Maybe somebody knows exactly which informations are
  814.      important and which not.
  815.  
  816.      Another idea is that we try the null-move first and generate the
  817.      moves later.  This may save time but we have to take care that
  818.      PV and other variables contain the right value so that the move
  819.      ordering works right.
  820.      */
  821.       register struct GameRec *g;
  822.       
  823.       nxtline[ply + 1] = 0;
  824.       CptrFlag[ply] = 0;
  825.       PawnThreat[ply] = 0;
  826.       Tscore[ply] = score;
  827.       /*PVsave = PV;
  828.       PV = 0;*/
  829.       null = 1;
  830.       g = &GameList[++GameCnt];
  831.       g->hashkey = hashkey;
  832.       g->hashbd = hashbd;
  833.       epsquare = -1;
  834.       TOsquare = -1;
  835.       g->Game50 = Game50;
  836. #ifdef LONGINTS
  837.       g->gmove = 0xffffffff;
  838. #else
  839.       g->gmove = 0xffff;
  840. #endif
  841.       g->flags = 0;
  842.       g->piece = 0;
  843.       g->color = neutral;
  844.       
  845.       best = -search(xside, ply+1, depth - 2, -beta-1, -beta, nxtline,&rcnt);
  846.       null = 0;
  847.       /*PV = PVsave;*/
  848.       GameCnt--;
  849.       if (best > beta)
  850.      return (best);
  851.       else
  852.      best = -12000;
  853.     }
  854. #endif
  855.   /* if best so far is better than alpha set alpha to best */
  856.     if(best>alpha)alpha=best;
  857.   /********************** main loop ************************************************************************/
  858.   /* look at each move until no more or beta cutoff */
  859.   for (pnt = pbst = TrPnt[ply]; pnt < TrPnt[ply + 1] && best <= beta; pnt++)
  860.     {
  861.       /* find the most interesting looking of the remaining moves */
  862.       if (ply > 1)
  863.     pick (pnt, TrPnt[ply + 1] - 1);
  864. #ifdef NULLMOVE
  865.       PVari = PVarisave && (pnt == TrPnt[ply]);  /* Is this the PV? */
  866. #endif
  867.  
  868.       node = &Tree[pnt];
  869.       /* is this a forbidden move */
  870.       if (ply == 1 && node->score == -32768)
  871.     continue;
  872. #ifdef DEBUG
  873.     if(debuglevel & (512 | 1024)){
  874.         if(!tracen)traceflag = ((ply >traceply)?false:true);
  875.          else
  876.         if(ply <= tracen && (ply ==1 || traceflag))
  877.             { 
  878.             if(trace[ply] == (Tree[pnt].t |(Tree[pnt].f<<8))) traceflag = true; else traceflag = false; }
  879.         tracelog[ply] = (Tree[pnt].t |(Tree[pnt].f<<8));
  880.         tracelog[ply+1] = 0;
  881. }
  882. #endif
  883.       nxtline[ply + 1] = 0;
  884.  
  885. #if !defined CHESSTOOL && !defined XBOARD
  886.       /* if at top level */
  887.       if (ply == 1)
  888.     {            /* at the top update search status */
  889.       if (flag.post)
  890. #ifdef QUIETBACKGROUND
  891.         if (!background)
  892. #endif /* QUIETBACKGROUND */
  893.           ShowCurrentMove (pnt, node->f, node->t);
  894.     }
  895. #endif
  896.       if (!(node->flags & exact))
  897.     {
  898.       /* make the move and go deeper */
  899.       MakeMove (side, node, &tempb, &tempc, &tempsf, &tempst, &INCscore);
  900.       CptrFlag[ply] = (node->flags & capture);
  901.       PawnThreat[ply] = (node->flags & pwnthrt);
  902.       Tscore[ply] = node->score;
  903.       PV = node->reply;
  904. #ifdef DEBUG
  905.       xxxtmp = node->score;
  906.       tracetmp = traceflag;
  907. #endif
  908.       node->score = -search (xside, ply + 1,
  909.                  (depth > 0)?depth-1:0,
  910.                  -beta, -alpha,
  911.                  nxtline, &rcnt);
  912.       node->width = (ply % 2 == 1) ? (TrPnt[ply + 2] - TrPnt[ply + 1]) : 0;
  913.       if (abs (node->score) > 9000) node->flags |= exact;
  914.       else if (rcnt == 1) node->score /= 2;
  915. #include "debug256.h"
  916.       if ((rcnt >= 2 || GameCnt - Game50 > 99 || (node->score == 9999 - ply && !ChkFlag[ply])))
  917.         {
  918.           node->flags |= (draw | exact);
  919.           DRAW = CP[58];    /* Draw */
  920.           node->score = ((side == computer) ? contempt : -contempt);
  921.         }
  922.       node->reply = nxtline[ply + 1];
  923.       /* reset to try next move */
  924.       UnmakeMove (side, node, &tempb, &tempc, &tempsf, &tempst);
  925.     }
  926.       /* if best move so far */
  927.       if (!flag.timeout && ((node->score > best) || ((node->score == best) && (node->width > bestwidth))))
  928.     {
  929.       /*
  930.        * all things being equal pick the denser part of the
  931.        * tree
  932.        */
  933.       bestwidth = node->width;
  934.  
  935.       /*
  936.        * if not at goal depth and better than alpha and not
  937.        * an exact score increment by depth
  938.        */
  939.       if (depth > 0 && node->score > alpha && !(node->flags & exact))
  940.         node->score += depth;
  941.       best = node->score;
  942.       pbst = pnt;
  943.       if (best > alpha) { alpha = best; }
  944.       /* update best line */
  945.       for (j = ply + 1; nxtline[j] > 0; j++) bstline[j] = nxtline[j];
  946.       bstline[j] = 0;
  947.       bstline[ply] = (node->f << 8) | node->t;
  948.       /* if at the top */
  949.       if (ply == 1)
  950.         {
  951.           /*
  952.            * if its better than the root score make it
  953.            * the root
  954.            */
  955.           if ((best > root->score) || ((best == root->score) && (bestwidth > root->width)))
  956.         {
  957.           tmp = Tree[pnt];
  958.           for (j = pnt - 1; j >= 0; j--) Tree[j + 1] = Tree[j];
  959.           Tree[0] = tmp;
  960.           pbst = 0;
  961.         }
  962. #if !defined CHESSTOOL && !defined XBOARD
  963. #ifdef QUIETBACKGROUND
  964.           if (!background)
  965. #endif /* QUIETBACKGROUND */
  966.         if (Sdepth > 2)
  967.           if (best > beta)
  968.             {
  969.               ShowResults (best, bstline, '+');
  970. #ifdef DEBUG41
  971.               debug41 (best, bstline, '+');
  972. #endif
  973.             }
  974.           else if (best < alpha)
  975.             {
  976.               ShowResults (best, bstline, '-');
  977. #ifdef DEBUG41
  978.               debug41 (best, bstline, '-');
  979. #endif
  980.             }
  981.           else
  982.             ShowResults (best, bstline, '&');
  983. #ifdef DEBUG41
  984.           debug41 (best, bstline, '&');
  985. #endif
  986. #else
  987.        if(!background && Sdepth >2 && best < alpha){
  988.         ExtraTime=8*TCleft;
  989.        }
  990. #endif
  991.         }
  992.     }
  993.       if (flag.timeout)
  994.     {
  995.       return (Tscore[ply - 1]);
  996.     }
  997.     }
  998.  
  999.   /******************************************************************************************/
  1000.   node = &Tree[pbst];
  1001.   mv = (node->f << 8) | node->t;
  1002. #ifdef NULLMOVE
  1003.   PVari = PVarisave;
  1004. #endif
  1005. #ifdef DEBUG
  1006. #include "debug512.h"
  1007. #endif
  1008.  
  1009.   /*
  1010.    * we have a move so put it in local table - if it's already there
  1011.    * done else if not there or needs to be updated also put it in
  1012.    * hashfile
  1013.    */
  1014. #if ttblsz
  1015.   if (flag.hash && ply <= Sdepth && *rpt == 0 && best == alpha)
  1016.     {
  1017. #ifdef notdef
  1018. algbr(node->f,node->t,0);
  1019. printf("IN-> %lx %lx %d %d %s\n",hashkey,hashbd,depth,side,mvstr[0]);
  1020. #endif
  1021.       if (PutInTTable (side, best, depth, ply, alpha, beta, mv)
  1022. #ifdef HASHFILE
  1023.       && hashfile && (depth > HashDepth) && (GameCnt < HashMoveLimit))
  1024.     {
  1025. #ifdef notdef
  1026. printf("FT %d %d %d %x\n",side,best,depth,mv);
  1027. #endif
  1028.       PutInFTable (side, best, depth, ply, alpha, beta, node->f, node->t);
  1029.     }
  1030. #else
  1031.     );
  1032. #endif /* HASHFILE */
  1033.     }
  1034. #endif /* ttblsz */
  1035.   if (depth > 0)
  1036.     {
  1037. #ifdef HISTORY
  1038.       j = (node->f << 6) | node->t;
  1039.       if (side == black)
  1040.     j |= 0x4000;
  1041.       if (history[j] < HISTORYLIM)
  1042.     history[j] += (unsigned short) 1<<depth;
  1043. #endif
  1044.       if (node->t != (short)(GameList[GameCnt].gmove & 0xFF))
  1045.     if (best <= beta)
  1046.       killr3[ply] = mv;
  1047.     else if (mv != killr1[ply])
  1048.       {
  1049.         killr2[ply] = killr1[ply];
  1050.         killr1[ply] = mv;
  1051.       }
  1052.       killr0[ply] = ((best > 9000) ? mv : 0);
  1053.     }
  1054.   return (best);
  1055. }
  1056.  
  1057.  
  1058.  
  1059.  
  1060. int
  1061. castle (short int side, short int kf, short int kt, short int iop)
  1062.  
  1063. /* Make or Unmake a castling move. */
  1064.  
  1065. {
  1066.   register short rf, rt, t0, xside;
  1067.  
  1068.   xside = side ^ 1;
  1069.   if (kt > kf)
  1070.     {
  1071.       rf = kf + 3;
  1072.       rt = kt - 1;
  1073.     }
  1074.   else
  1075.     {
  1076.       rf = kf - 4;
  1077.       rt = kt + 1;
  1078.     }
  1079.   if (iop == 0)
  1080.     {
  1081.       if (kf != kingP[side] ||
  1082.       board[kf] != king ||
  1083.       board[rf] != rook ||
  1084.       color[kf] != side ||
  1085.       color[rf] != side ||
  1086.       Mvboard[kf] != 0 ||
  1087.       Mvboard[rf] != 0 ||
  1088.       color[kt] != neutral ||
  1089.       color[rt] != neutral ||
  1090.       color[kt - 1] != neutral ||
  1091.       SqAtakd3 (kf, xside) ||
  1092.       SqAtakd3 (kt, xside) ||
  1093.       SqAtakd3 (rt, xside))
  1094.     return (false);
  1095.     }
  1096.   else
  1097.     {
  1098.       if (iop == 1)
  1099.     {
  1100.           Castled[side] = 1;
  1101.       castld[side] = true;
  1102.       Mvboard[kf]++;
  1103.       Mvboard[rf]++;
  1104.     }
  1105.       else
  1106.     {
  1107.           Castled[side] = 0;
  1108.       castld[side] = false;
  1109.       Mvboard[kf]--;
  1110.       Mvboard[rf]--;
  1111.       t0 = kt;
  1112.       kt = kf;
  1113.       kf = t0;
  1114.       t0 = rt;
  1115.       rt = rf;
  1116.       rf = t0;
  1117.     }
  1118.       board[kt] = king;
  1119.       color[rt] = color[kt] = side;
  1120.       Pindex[kt] = 0;
  1121.       board[kf] = no_piece;
  1122.       color[rf] = color[kf] = neutral;
  1123.       board[rt] = rook;
  1124.       Pindex[rt] = Pindex[rf];
  1125.       board[rf] = no_piece;
  1126.       PieceList[side][Pindex[kt]] = kt;
  1127.       PieceList[side][Pindex[rt]] = rt;
  1128.       UpdateHashbd (side, king, kf, kt);
  1129.       UpdateHashbd (side, rook, rf, rt);
  1130.     }
  1131.   return (true);
  1132. }
  1133.  
  1134.  
  1135. void
  1136. EnPassant (short int xside, short int f, short int t, short int iop)
  1137.  
  1138. /*
  1139.  * Make or unmake an en passant move.
  1140.  */
  1141.  
  1142. {
  1143.   register short l;
  1144.  
  1145.   l = t + ((t > f) ? -8 : 8);
  1146.   if (iop == 1)
  1147.     {
  1148.       myEnPassant[xside] = 1;
  1149.       board[l] = no_piece;
  1150.       color[l] = neutral;
  1151.     }
  1152.   else
  1153.     {
  1154.       board[l] = pawn;
  1155.       color[l] = xside;
  1156.       myEnPassant[xside] = 0;
  1157.     }
  1158.   InitializeStats ();
  1159. }
  1160.  
  1161.  
  1162. void
  1163. UpdatePieceList (short int side, short int sq, short int iop)
  1164.  
  1165. /*
  1166.  * Update the PieceList and Pindex arrays when a piece is captured or when a
  1167.  * capture is unmade.
  1168.  */
  1169.  
  1170. {
  1171.   register short i;
  1172.  
  1173.   if (iop == 1)
  1174.     {
  1175.       PieceCnt[side]--;
  1176.       for (i = Pindex[sq]; i <= PieceCnt[side]; i++)
  1177.     {
  1178.       PieceList[side][i] = PieceList[side][i + 1];
  1179.       Pindex[PieceList[side][i]] = i;
  1180.     }
  1181.     }
  1182.   else
  1183.     {
  1184.       PieceCnt[side]++;
  1185.       PieceList[side][PieceCnt[side]] = sq;
  1186.       Pindex[sq] = PieceCnt[side];
  1187.     }
  1188. }
  1189.  
  1190. void
  1191. MakeMove (short int side,
  1192.       struct leaf *node,
  1193.       short int *tempb,    /* color of to square */
  1194.       short int *tempc,    /* piece at to square */
  1195.       short int *tempsf,    /* static value of piece on from */
  1196.       short int *tempst,    /* static value of piece on to */
  1197.       short int *INCscore)    /* score increment for pawn structure change */
  1198.  
  1199. /*
  1200.  * Update Arrays board[], color[], and Pindex[] to reflect the new board
  1201.  * position obtained after making the move pointed to by node. Also update
  1202.  * miscellaneous stuff that changes when a move is made.
  1203.  */
  1204.  
  1205. {
  1206.   register short f, t, xside, ct, cf;
  1207.   register struct GameRec *g;
  1208.  
  1209.   xside = side ^ 1;
  1210.   g = &GameList[++GameCnt];
  1211.   g->hashkey = hashkey;
  1212.   g->hashbd = hashbd;
  1213.   g->epssq = epsquare;
  1214.   f = node->f;
  1215.   t = node->t;
  1216.   epsquare = -1;
  1217.   /* FROMsquare = f;*/
  1218.   TOsquare = t;
  1219.   *INCscore = 0;
  1220.   g->Game50 = Game50;
  1221.   g->gmove = (f << 8) | t;
  1222.   g->flags = node->flags;
  1223.   if (node->flags & cstlmask)
  1224.     {
  1225.       g->piece = no_piece;
  1226.       g->color = side;
  1227.       (void) castle (side, f, t, 1);
  1228.       Game50 = GameCnt;
  1229.     }
  1230.   else
  1231.     {
  1232.       if (!(node->flags & capture) && (board[f] != pawn))
  1233.     rpthash[side][hashkey & 0xFF]++;
  1234.       else
  1235.     Game50 = GameCnt;
  1236.       *tempsf = svalue[f];
  1237.       *tempst = svalue[t];
  1238.       g->piece = *tempb = board[t];
  1239.       g->color = *tempc = color[t];
  1240.       if (*tempc != neutral)
  1241.     {
  1242.       UpdatePieceList (*tempc, t, 1);
  1243.       /* if capture decrement pawn count */
  1244.       if (*tempb == pawn)
  1245.         {
  1246.           --PawnCnt[*tempc][column (t)];
  1247.         }
  1248.       if (board[f] == pawn)
  1249.         {
  1250.           cf = column (f);
  1251.           ct = column (t);
  1252.           /* move count from from to to */
  1253.           --PawnCnt[side][cf];
  1254.           ++PawnCnt[side][ct];
  1255.  
  1256.           /*
  1257.            * calculate increment for pawn structure
  1258.            * changes
  1259.            */
  1260.           /* doubled or more - */
  1261.           if (PawnCnt[side][ct] > (1 + PawnCnt[side][cf]))
  1262.         *INCscore -= 15;
  1263.           /* went to empty column + */
  1264.           else if (PawnCnt[side][ct] < 1 + PawnCnt[side][cf])
  1265.         *INCscore += 15;
  1266.  
  1267.           /*
  1268.            * went to outside col or empty col on one
  1269.            * side ????????
  1270.            */
  1271.           else if (ct == 0 || ct == 7 || PawnCnt[side][ct + ct - cf] == 0)
  1272.         *INCscore -= 15;
  1273.         }
  1274.       mtl[xside] -= value[*tempb];
  1275.       if (*tempb == pawn)
  1276.         pmtl[xside] -= valueP;
  1277.       UpdateHashbd (xside, *tempb, -1, t);
  1278.       *INCscore += *tempst;
  1279.       Mvboard[t]++;
  1280.     }
  1281.       color[t] = color[f];
  1282.       board[t] = board[f];
  1283.       svalue[t] = svalue[f];
  1284.       Pindex[t] = Pindex[f];
  1285.       PieceList[side][Pindex[t]] = t;
  1286.       color[f] = neutral;
  1287.       board[f] = no_piece;
  1288.       if (board[t] == pawn)
  1289.     if (t - f == 16)
  1290.       epsquare = f + 8;
  1291.     else if (f - t == 16)
  1292.       epsquare = f - 8;
  1293.       if (node->flags & promote)
  1294.     {
  1295.       board[t] = node->flags & pmask;
  1296.       if (board[t] == queen)
  1297.         HasQueen[side]++;
  1298.       else if (board[t] == rook)
  1299.         HasRook[side]++;
  1300.       else if (board[t] == bishop)
  1301.         HasBishop[side]++;
  1302.       else if (board[t] == knight)
  1303.         HasKnight[side]++;
  1304.       --PawnCnt[side][column (t)];
  1305.       mtl[side] += value[board[t]] - valueP;
  1306.       pmtl[side] -= valueP;
  1307.       UpdateHashbd (side, pawn, f, -1);
  1308.       UpdateHashbd (side, board[t], f, -1);
  1309.       *INCscore -= *tempsf;
  1310.     }
  1311.       if (node->flags & epmask)
  1312.     EnPassant (xside, f, t, 1);
  1313.       else
  1314.     UpdateHashbd (side, board[t], f, t);
  1315.       Mvboard[f]++;
  1316.     }
  1317. }
  1318.  
  1319. void
  1320. UnmakeMove (short int side,
  1321.         struct leaf *node,
  1322.         short int *tempb,
  1323.         short int *tempc,
  1324.         short int *tempsf,
  1325.         short int *tempst)
  1326.  
  1327. /*
  1328.  * Take back a move.
  1329.  */
  1330.  
  1331. {
  1332.   register short f, t, xside;
  1333.  
  1334.   xside = side ^ 1;
  1335.   f = node->f;
  1336.   t = node->t;
  1337.   Game50 = GameList[GameCnt].Game50;
  1338.   if (node->flags & cstlmask)
  1339.     (void) castle (side, f, t, 2);
  1340.   else
  1341.     {
  1342.       color[f] = color[t];
  1343.       board[f] = board[t];
  1344.       svalue[f] = *tempsf;
  1345.       Pindex[f] = Pindex[t];
  1346.       PieceList[side][Pindex[f]] = f;
  1347.       color[t] = *tempc;
  1348.       board[t] = *tempb;
  1349.       svalue[t] = *tempst;
  1350.       if (node->flags & promote)
  1351.     {
  1352.       board[f] = pawn;
  1353.       ++PawnCnt[side][column (t)];
  1354.       mtl[side] += valueP - value[node->flags & pmask];
  1355.       pmtl[side] += valueP;
  1356.       UpdateHashbd (side, (short) node->flags & pmask, -1, t);
  1357.       UpdateHashbd (side, pawn, -1, t);
  1358.     }
  1359.       if (*tempc != neutral)
  1360.     {
  1361.       UpdatePieceList (*tempc, t, 2);
  1362.       if (*tempb == pawn)
  1363.         {
  1364.           ++PawnCnt[*tempc][column (t)];
  1365.         }
  1366.       if (board[f] == pawn)
  1367.         {
  1368.           --PawnCnt[side][column (t)];
  1369.           ++PawnCnt[side][column (f)];
  1370.         }
  1371.       mtl[xside] += value[*tempb];
  1372.       if (*tempb == pawn)
  1373.         pmtl[xside] += valueP;
  1374.       UpdateHashbd (xside, *tempb, -1, t);
  1375.       Mvboard[t]--;
  1376.     }
  1377.       if (node->flags & epmask)
  1378.     {
  1379.       EnPassant (xside, f, t, 2);
  1380.     }
  1381.       else
  1382.     UpdateHashbd (side, board[f], f, t);
  1383.       Mvboard[f]--;
  1384.       if (!(node->flags & capture) && (board[f] != pawn))
  1385.     rpthash[side][hashkey & 0xFF]--;
  1386.     }
  1387.   epsquare = GameList[GameCnt--].epssq;
  1388. }
  1389.  
  1390.  
  1391. void
  1392. InitializeStats (void)
  1393.  
  1394. /*
  1395.  * Scan thru the board seeing what's on each square. If a piece is found,
  1396.  * update the variables PieceCnt, PawnCnt, Pindex and PieceList. Also
  1397.  * determine the material for each side and set the hashkey and hashbd
  1398.  * variables to represent the current board position. Array
  1399.  * PieceList[side][indx] contains the location of all the pieces of either
  1400.  * side. Array Pindex[sq] contains the indx into PieceList for a given
  1401.  * square.
  1402.  */
  1403.  
  1404. {
  1405.   register short i, sq;
  1406.  
  1407.   epsquare = -1;
  1408.   for (i = 0; i < 8; i++)
  1409.     {
  1410.       PawnCnt[white][i] = PawnCnt[black][i] = 0;
  1411.     }
  1412.   mtl[white] = mtl[black] = pmtl[white] = pmtl[black] = 0;
  1413.   PieceCnt[white] = PieceCnt[black] = 0;
  1414.   hashbd = hashkey = 0;
  1415.   for (sq = 0; sq < 64; sq++)
  1416.     if (color[sq] != neutral)
  1417.       {
  1418.     mtl[color[sq]] += value[board[sq]];
  1419.     if (board[sq] == pawn)
  1420.       {
  1421.         pmtl[color[sq]] += valueP;
  1422.         ++PawnCnt[color[sq]][column (sq)];
  1423.       }
  1424.     Pindex[sq] = ((board[sq] == king) ? 0 : ++PieceCnt[color[sq]]);
  1425.  
  1426.     PieceList[color[sq]][Pindex[sq]] = sq;
  1427.     hashbd ^= hashcode[color[sq]][board[sq]][sq].bd;
  1428.     hashkey ^= hashcode[color[sq]][board[sq]][sq].key;
  1429.       }
  1430. }
  1431.